package cmp.compile.panels;
/*****************************************************
 * Top panel  of multiTCW window
 */
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.sql.ResultSet;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
import javax.swing.JTextField;

import util.Debug.ErrorReport;
import util.ui.UserPrompt;
import cmp.compile.CompileMain;
import assem.DBConn;
import cmp.main.Globals;

public class ProjectPanel extends JPanel {
	private static final long serialVersionUID = -5440876354212703010L;

	public ProjectPanel(CompilePanel parentPanel) {
		theParentPanel = parentPanel;
		
		String [] projNames = CompilePanel.getProjectNames();
		
		cmbProject = new JComboBox();
		cmbProject.addItem("Select...");
		for(int x=0; x<projNames.length; x++)
			cmbProject.addItem(projNames[x]);
		cmbProject.setSelectedIndex(0);
		cmbProject.setBackground(Globals.BGCOLOR);
		cmbProject.setMaximumSize(cmbProject.getPreferredSize());
		cmbProject.setMinimumSize(cmbProject.getPreferredSize());
		cmbProject.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				clearData();
				if(cmbProject.getSelectedIndex() > 0) {
					theParentPanel.setProjectSelected(true);
					theParentPanel.loadCPAVE();
					if(doesDBExist()) {
						theParentPanel.getMethodPanel().validateMethods(true);
					}
				}
				else {
					theParentPanel.setProjectSelected(false);
				}
				theParentPanel.getBlastPanel().setBlastSummary();
			}
		});
		
		btnSave = new JButton("Save");
		btnSave.setBackground(Globals.BGCOLOR);
		btnSave.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if(cmbProject.getSelectedIndex() > 0)
					theParentPanel.saveCPAVE();
			}
		});
		
		btnAdd = new JButton("Add Project");
		btnAdd.setBackground(Globals.PROMPTCOLOR);
		btnAdd.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				try {
					String newProjectName = null;
					boolean valid = true;
					do {
						newProjectName = JOptionPane.showInputDialog(theParentPanel.getParentFrame(), 
						        "Enter new project name", Globals.CMPDBPREFIX, JOptionPane.PLAIN_MESSAGE);
						if(newProjectName != null) {
							
							valid = true;
							if (!newProjectName.matches("[\\w\\d]+"))
							{
								JOptionPane.showMessageDialog(theParentPanel, "Name contains invalid characters.\nUse letters,numbers,underscores.",
										"Invalid name", JOptionPane.PLAIN_MESSAGE);
								System.err.println("Error: name contains invalid characters");
								valid = false;
							}
							else
							{
								String projDir = Globals.PROJECTDIR + "/" + newProjectName + "/";// + CONFIGFILE;
								File temp = new File(projDir);
								
								if(temp.exists()) { // CAS 12/22/14 - was just ignoring if existed
									System.err.println("Project exists: " + projDir);
									projDir += Globals.CONFIG_FILE;
									temp = new File(projDir);
									if (!temp.exists())
										(new File(projDir)).createNewFile();
								}
								else {
									System.err.println("New project: " + projDir);
									temp.mkdir();
									projDir += Globals.CONFIG_FILE;
									(new File(projDir)).createNewFile();
								}
							}
						}
					} while(!valid && newProjectName != null);
					
					if(newProjectName != null) {
						updateProjectList(newProjectName);
						theParentPanel.saveCPAVE();
						theParentPanel.pnlBlast.editPanel.fillEmptyFieldsWithDefaults(); 
						theParentPanel.pnlBlast.editPanel.setUseBlast(false);
					}
				}
				catch(Exception e) {
					ErrorReport.prtReport(e, "Error creating new project");
				}
			}
		});
		btnHelp = new JButton("Help");
		btnHelp.setBackground(Globals.HELPCOLOR);
		btnHelp.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent arg0) {
				UserPrompt.displayHTMLResourceHelp(theParentPanel.getParentFrame(), 
						"runMultiTCW", "html/runMultiTCW/ManagerPanel.html");
			}
		});
		// CAS 5July15 change to act like runSingleTCW
		btnRemove = new JButton("Remove...");
		btnRemove.setBackground(Globals.PROMPTCOLOR);
		btnRemove.setAlignmentX(Component.RIGHT_ALIGNMENT);
		final JPopupMenu popup = new JPopupMenu();
		
		popup.add(new JMenuItem(new AbstractAction("Remove SQL database") {
			private static final long serialVersionUID = 4692812516440639008L;
			public void actionPerformed(ActionEvent e) {
				int ret = JOptionPane.showOptionDialog(null, "Confirm: remove SQL database",
						"runSingleTCW", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
				if (ret == JOptionPane.YES_OPTION)
				{
					System.err.println("Removing SQL database...");
					removeSelectedDatabase(false);
					updateUI();
				}
			}
		}));
		
		popup.add(new JMenuItem(new AbstractAction("Remove project files from disk") {
			private static final long serialVersionUID = 4692812516440639008L;
			public void actionPerformed(ActionEvent e) {
				int ret = JOptionPane.showOptionDialog(null, "Confirm: remove project files",
						"runSingleTCW", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
				if (ret == JOptionPane.YES_OPTION)
				{
					System.err.println("Removing project files ...");
					removeSelectedProject();
				}
			}
		}));
		popup.add(new JMenuItem(new AbstractAction("Remove both") {
			private static final long serialVersionUID = 4692812516440639008L;
			public void actionPerformed(ActionEvent e) {
				int ret = JOptionPane.showOptionDialog(null, "Confirm: remove both",
						"runSingleTCW", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
				if (ret == JOptionPane.YES_OPTION)
				{
					System.err.println("Removing SQL database...");
					removeSelectedDatabase(true); // don't prompt to delete blast
					System.err.println("Removing project files ...");
					removeSelectedProject();
				}
			}
		}));
		btnRemove.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                popup.show(e.getComponent(), e.getX(), e.getY());
            }
        });

		btnGetState = new JButton("Overview");
		btnGetState.setBackground(Globals.LAUNCHCOLOR);
		btnGetState.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				try {
					String val = null;
					if(txtDBName.getText().length() == 0) {
						System.out.println("No database name set");
						return;
					}
					String dbName = txtDBName.getText();
						
					if(!CompilePanel.hosts.checkDBConnect(dbName))
						val = "No database available";
						
					if(val == null) {
						DBConn conn = CompilePanel.hosts.getDBConn(dbName);
						ResultSet rset = conn.executeQuery("SELECT summary FROM info");
							
						if(rset.first()) {
							val = rset.getString(1);
						}
						rset.close();
						conn.close();
					}
					UserPrompt.displayInfoMonoSpace(null, "Overview of " + dbName, val.split("\n"), false, true);
				}
				catch(Exception e) {
					ErrorReport.prtReport(e, "Error getting project state");
				}
			}
		});
		txtDBName = new JTextField(20);
		txtDBName.setMaximumSize(txtDBName.getPreferredSize());
		txtDBName.setMinimumSize(txtDBName.getPreferredSize());
		
		mainPanel = CompilePanel.getPanel(false);
		JPanel temp = CompilePanel.getPanel(true);
		
		temp.add(btnAdd);
		temp.add(Box.createHorizontalStrut(10));
		temp.add(btnHelp);
		temp.setMaximumSize(temp.getPreferredSize());
		temp.setMinimumSize(temp.getPreferredSize());
		
		mainPanel.add(temp);
		mainPanel.add(Box.createVerticalStrut(10));

		temp = CompilePanel.getPanel(true);
		temp.add(new JLabel("Project"));
		temp.add(Box.createHorizontalStrut(5));
		temp.add(cmbProject);
		temp.add(Box.createHorizontalStrut(10));
		temp.add(btnSave);
		temp.add(Box.createHorizontalStrut(10));
		temp.add(btnRemove);
		temp.add(Box.createHorizontalStrut(10));
		temp.add(btnGetState);
		temp.setMaximumSize(temp.getPreferredSize());
		temp.setMinimumSize(temp.getPreferredSize());

		mainPanel.add(temp);
		
		temp = CompilePanel.getPanel(true);
		
		lblDBName = new JLabel("DB Name"); 
		temp.add(lblDBName);
		temp.add(Box.createHorizontalStrut(5));
		temp.add(txtDBName);
		temp.add(Box.createHorizontalStrut(15));
		temp.add(new JLabel("Host: " + CompilePanel.hosts.host));
		temp.setMaximumSize(temp.getPreferredSize());
		temp.setMinimumSize(temp.getPreferredSize());
		
		mainPanel.add(Box.createVerticalStrut(20));
		mainPanel.add(temp);
		mainPanel.add(Box.createVerticalStrut(10));
		mainPanel.add(new JSeparator());
		
		setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));

		add(mainPanel);
	}
	
	private void removeSelectedDatabase(boolean noPrompt) {
		try
		{
			boolean valid = CompileMain.hosts.checkDBConnect(getDBName());
			
			if(valid) {
				DBConn conn = CompileMain.hosts.getDBConn(getDBName());
				conn.executeUpdate("drop database " + getDBName());
				System.err.println("Successfully removed " + getDBName());
				theParentPanel.getMethodPanel().clearAllLoaded();
				conn.close();
			}
			else {
				System.err.println("Error: Database '" + getDBName() + "' does not exist on " + CompileMain.hosts.host);
			}

			if (!noPrompt) {
				String blastDir = theParentPanel.getCurrentProjectDirectory() +  "/" + Globals.CompilePanel.BLASTDIR; 
				if((new File(blastDir)).exists()) {
					if(JOptionPane.showConfirmDialog(this, 
							"Delete blast Results/ ?", "Remove Blast", JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE) == JOptionPane.YES_OPTION) {
						deleteDir(new File(blastDir));
						theParentPanel.getBlastPanel().setBlastSummary();
						System.err.println("Done");
					}
				}
			}
		} 
		catch (Exception e)
		{
			ErrorReport.reportError(e, "Cannot delete database " + getDBName());
		}
	}
	
	private boolean deleteDir(File f) {
		boolean retVal = true;
		if(f.isDirectory()) {
			for (File subFile : f.listFiles())
				retVal = retVal && deleteDir(subFile);
		}
		boolean delResult = f.delete();
		if(delResult)
			System.out.println("Deleting: " + f.getAbsolutePath());
		else
			System.out.println("Failed to delete " + f.getAbsolutePath());
		
		return retVal && delResult;
	}
	
	private void removeSelectedProject() {
		try {
			
			File fLib = new File(theParentPanel.getCurrentProjectDirectory());
			if (CompileMain.logFileObj != null)
			{
				CompileMain.logFileObj.close();
			}
			deleteDir(fLib);
			
			updateProjectList(null);
			updateUI();
			System.err.println("Project deleted");
		}
		catch(Exception e) {
			ErrorReport.prtReport(e, "Error removing project");
		}
	}
	
	public boolean doesDBExist() {
		if(txtDBName.getText().length() == 0)
			return false;
		return CompileMain.hosts.checkDBConnect(txtDBName.getText());
	}
	
	public Vector<String> getLoadedMethodPrefixes() {
		if(txtDBName.getText().length() == 0)
			return null;
		return CompilePanel.getLoadedMethodPrefixes( txtDBName.getText());
	}
	
	public void clearData() {
		txtDBName.setText("");
	}
	
	public void setProjectSelected(boolean selected) {
		btnSave.setEnabled(selected);
		btnRemove.setEnabled(selected);
		btnGetState.setEnabled(selected);
		lblDBName.setEnabled(selected);
		txtDBName.setEnabled(selected);
	}
	
	private void updateProjectList(String projectName) {
		String [] projNames = CompilePanel.getProjectNames();

		cmbProject.removeAllItems();
		
		cmbProject.addItem("Select ...");
		for(int x=0; x<projNames.length; x++)
			cmbProject.addItem(projNames[x]);
		if(projectName == null)
			cmbProject.setSelectedIndex(0);
		else {
			cmbProject.setSelectedItem(projectName);
			System.out.println("Project: " + projectName);
		}
		
		cmbProject.setBackground(Globals.BGCOLOR);
		cmbProject.setMaximumSize(cmbProject.getPreferredSize());
		cmbProject.setMinimumSize(cmbProject.getPreferredSize());
		
		if(cmbProject.getSelectedIndex() > 0)
			txtDBName.setText(Globals.CMPDBPREFIX + "_" + projectName);
	}
	
	public String getSelectedProjectName() { 
		if(cmbProject.getSelectedIndex() == 0) 
			return null;
		else
			return (String) cmbProject.getSelectedItem();
	}
	
	public String getDBName() { return txtDBName.getText(); }
	public void setDBName(String dbName) { txtDBName.setText(dbName); }
	
	private CompilePanel theParentPanel = null;
	private JPanel mainPanel = null;
	private JComboBox cmbProject = null;
	private JButton btnSave = null;
	private JButton btnAdd = null;
	private JButton btnHelp = null;
	private JButton btnRemove = null;
	private JButton btnGetState = null;
	private JLabel lblDBName = null;
	private JTextField txtDBName = null;
}
